home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / tcilight.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  12.0 KB  |  522 lines

  1. /*
  2.  * Copyright 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18. ** Test Color Index Lighting
  19. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <math.h>
  24. #include <X11/Xlib.h>
  25. #include <X11/keysym.h>
  26. #include <GL/gl.h>
  27. #include <GL/glx.h>
  28.  
  29. float indexScale = 1.0;
  30.  
  31. int useLighting = 0;
  32. int useTwoSide = 0;
  33. int useLocalLight = 0;
  34. int useLocalViewer = 0;
  35. int useSpot = 0;
  36. int useAtten = 0;
  37. int whichObject = 0;
  38.  
  39. float modelAmb[4] = { 0.0, 0.0, 0.0, 0.0 };
  40.  
  41. float lightPosInf[4] = { 0.0, 0.0, 1.0, 0.0 };
  42. float lightPosLoc[4] = { 0.0, 0.0, 4.0, 1.0 };
  43. float lightAmb[4] = { 0.2, 0.2, 0.2, 0.0 };
  44. float lightDiff[4] = { 0.6, 0.6, 0.6, 0.0 };
  45. float lightSpec[4] = { 0.2, 0.2, 0.2, 0.0 };
  46. float lightSpotDir[3] = { 0.0, 0.0, -1.0 };
  47. float lightSpot[2] = { 100.0, 30.0 };
  48. float lightAtten[3] = { 0.80, 0.25, 0.05 };
  49.  
  50. float matIndexRange[3] = { 0.05, 0.75, 0.95 };
  51. float matIndexes[3] = { 0.0, 0.0, 0.0 };
  52. float matShininess[1] = { 10.0 };
  53.  
  54. static void
  55. init(void)
  56. {
  57.     glClearIndex(0.0);
  58.  
  59.     glMatrixMode(GL_PROJECTION);
  60.     glLoadIdentity();
  61.     glFrustum(-1, 1, -1, 1, 1, 3);
  62.  
  63.     glMatrixMode(GL_MODELVIEW);
  64.     glLoadIdentity();
  65.     glTranslatef(0.0, 0.0, -2.0);
  66.  
  67.     glEnable(GL_DEPTH_TEST);
  68.     glEnable(GL_NORMALIZE);
  69.  
  70.     glLineWidth(2.0);
  71. }
  72.  
  73. static void
  74. reconfig(void)
  75. {
  76.     glLightModelfv(GL_AMBIENT, modelAmb);
  77.     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, useLocalViewer);
  78.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, useTwoSide);
  79.  
  80.     glLightfv(GL_LIGHT0, GL_POSITION, useLocalLight ? lightPosLoc:lightPosInf);
  81.     glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
  82.     glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff);
  83.     glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpec);
  84.     glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightSpotDir);
  85.     glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, useSpot ? lightSpot[0]:1.0);
  86.     glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, useSpot ? lightSpot[1]:180.0);
  87.     glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, useAtten ? lightAtten[0]:1.0);
  88.     glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, useAtten ? lightAtten[1]:0.0);
  89.     glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, useAtten ? lightAtten[2]:0.0);
  90.     glEnable(GL_LIGHT0);
  91.  
  92.     matIndexes[0] = matIndexRange[0]*indexScale;
  93.     matIndexes[1] = matIndexRange[1]*indexScale;
  94.     matIndexes[2] = matIndexRange[2]*indexScale;
  95.     glMaterialfv(GL_FRONT_AND_BACK, GL_COLOR_INDEXES, matIndexes);
  96.     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, matShininess);
  97.  
  98.     if (useLighting) {
  99.     glEnable(GL_LIGHTING);
  100.     } else {
  101.     glDisable(GL_LIGHTING);
  102.     }
  103.  
  104. }
  105.  
  106. static void
  107. drawMaterialMeter(void)
  108. {
  109.     if (useLighting) glDisable(GL_LIGHTING);
  110.  
  111.     glPushMatrix();
  112.     glLoadIdentity();
  113.     glTranslatef(0.7, -0.9, -1.0);
  114.     glScalef(0.2, 1.8, 1.0);
  115.  
  116.     glBegin(GL_LINES);
  117.     glIndexf(0.95*indexScale);
  118.     glVertex2f(0.0, 0.0); glVertex2f(1.0, 0.0);
  119.     glVertex2f(1.0, 0.0); glVertex2f(1.0, 1.0);
  120.     glVertex2f(1.0, 1.0); glVertex2f(0.0, 1.0);
  121.     glVertex2f(0.0, 1.0); glVertex2f(0.0, 0.0);
  122.  
  123.     glIndexf(0.25*indexScale);
  124.     glVertex2f(0.0, matIndexRange[0]); glVertex2f(1.0, matIndexRange[0]);
  125.  
  126.     glIndexf(0.50*indexScale);
  127.     glVertex2f(0.0, matIndexRange[1]); glVertex2f(1.0, matIndexRange[1]);
  128.  
  129.     glIndexf(0.75*indexScale);
  130.     glVertex2f(0.0, matIndexRange[2]); glVertex2f(1.0, matIndexRange[2]);
  131.     glEnd();
  132.  
  133.     glPopMatrix();
  134.  
  135.     if (useLighting) glEnable(GL_LIGHTING);
  136. }
  137.  
  138. static void
  139. drawGrid(void)
  140. {
  141.     static int dlist = 0;
  142.  
  143.     if (dlist) {
  144.     glCallList(dlist);
  145.     } else {
  146.     int u = 8, v = 8;
  147.     float du = 1.0 / u;
  148.     float dv = 1.0 / v;
  149.     int i, j;
  150.  
  151.     dlist = glGenLists(1);
  152.     glNewList(dlist, GL_COMPILE_AND_EXECUTE);
  153.  
  154.     glNormal3f(0.0, 0.0, 1.0);
  155.     glBegin(GL_QUADS);
  156.     for (j=0; j<v; ++j) {
  157.         float y = j * dv;
  158.  
  159.         for (i=0; i<u; ++i) {
  160.         float x = i * du;
  161.  
  162.         if ((i ^ j) & 1) {
  163.             glIndexf(0.25*indexScale);
  164.         } else {
  165.             glIndexf(0.75*indexScale);
  166.         }
  167.         glVertex2f(x   , y   );
  168.         glVertex2f(x+du, y   );
  169.         glVertex2f(x+du, y+dv);
  170.         glVertex2f(x   , y+dv);
  171.         }
  172.     }
  173.     glEnd();
  174.  
  175.     glEndList();
  176.     }
  177. }
  178.  
  179. static void
  180. drawCylinder(void)
  181. {
  182.     static int dlist = 0;
  183.  
  184.     if (dlist) {
  185.     glCallList(dlist);
  186.     } else {
  187.     int u = 16;
  188.     float du = (2*M_PI) / u;
  189.     int i, j;
  190.  
  191.     dlist = glGenLists(1);
  192.     glNewList(dlist, GL_COMPILE_AND_EXECUTE);
  193.  
  194.     glBegin(GL_TRIANGLE_STRIP);
  195.     for (i=0; i<=u; ++i) {
  196.         float t = i * du;
  197.         float x = 0.5 * (float)cos((double) t) + 0.5;
  198.         float y = 0.5 * (float)sin((double) t) + 0.5;
  199.  
  200.         glNormal3f(2.0 * (x - 0.5), 2.0 * (y - 0.5), 0.0);
  201.         glIndexf(0.80*indexScale);
  202.         glVertex3f(x, y,  0.5);
  203.         glIndexf(0.20*indexScale);
  204.         glVertex3f(x, y, -0.5);
  205.     }
  206.     glEnd();
  207.  
  208.     glEndList();
  209.     }
  210. }
  211.  
  212. #define NUM_OBJECTS 2
  213. static void (*drawObject[NUM_OBJECTS])(void) = { drawGrid, drawCylinder };
  214.  
  215. static void
  216. redraw(float xrot, float yrot)
  217. {
  218.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  219.  
  220.     drawMaterialMeter();
  221.  
  222.     glPushMatrix();
  223.     glRotatef(xrot, 1, 0, 0);
  224.     glRotatef(yrot, 0, 1, 0);
  225.  
  226.     glPushMatrix();
  227.     glScalef(1.5, 1.5, 1.25);
  228.     glTranslatef(-0.5, -0.5, 0.0);
  229.     (*drawObject[whichObject])();
  230.     glPopMatrix();
  231.  
  232.     glPopMatrix();
  233. }
  234.  
  235. static Colormap
  236. buildGrayScaleColormap(Display *dpy, XVisualInfo *vis)
  237. {
  238.     Colormap cmap;
  239.  
  240.     cmap = XCreateColormap(dpy, RootWindow(dpy, vis->screen),
  241.                vis->visual, AllocNone);
  242.  
  243.     if (vis->class == PseudoColor) {
  244.     int mapSize = 1 << vis->depth;
  245.     int firstEntry = 0;
  246.     int entry;
  247.     unsigned long *pix;
  248.  
  249.     pix = (unsigned long *) calloc(mapSize, sizeof(unsigned long));
  250.  
  251.     if (!XAllocColorCells(dpy, cmap, True, NULL, 0, pix, mapSize)) {
  252.         if (!XAllocColorCells(dpy, cmap, True, NULL, 0, pix, mapSize-1)) {
  253.         fprintf(stderr, "can't alloc enough colormap entries\n");
  254.         exit(EXIT_FAILURE);
  255.         }
  256.         firstEntry = 1;
  257.     }
  258.  
  259.     for (entry=firstEntry; entry<mapSize; ++entry) {
  260.         XColor col;
  261.         int val = entry * (0xffff / (mapSize-1));
  262.  
  263.         col.pixel = entry;
  264.         col.red   = val;
  265.         col.green = val;
  266.         col.blue  = val;
  267.         col.flags = DoRed | DoGreen | DoBlue;
  268.  
  269.         XStoreColor(dpy, cmap, &col);
  270.     }
  271.  
  272.     free((void *) pix);
  273.     } else {
  274.     fprintf(stderr, "can't build colormap for selected visual\n");
  275.     exit(EXIT_FAILURE);
  276.     }
  277.  
  278.     return cmap;
  279. }
  280.  
  281. static Bool
  282. waitForMapNotify(Display *dpy, XEvent *ev, XPointer arg)
  283. {
  284.     return ((ev->type == MapNotify) && (ev->xmapping.window == (Window) arg));
  285. }
  286.  
  287. static int visualAttrs[] = {
  288.     GLX_DOUBLEBUFFER,
  289.     GLX_BUFFER_SIZE, 4,
  290.     GLX_DEPTH_SIZE, 1,
  291.     GLX_LEVEL, 0,
  292.     None,
  293. };
  294.  
  295. int
  296. main(int argc, char **argv)
  297. {
  298.     Display *dpy;
  299.     int scrn;
  300.     Window root;
  301.     XVisualInfo *vis;
  302.     GLXContext ctx;
  303.     Colormap cmap;
  304.     XSizeHints sizehints;
  305.     XSetWindowAttributes swa;
  306.     Window win;
  307.     XEvent ev;
  308.     char *name = "ColorIndex Lighting";
  309.     char *geometry = NULL;
  310.     int x = 0;
  311.     int y = 0;
  312.     unsigned int width = 300;
  313.     unsigned int height = 300;
  314.     int needsReconfig = 1;
  315.     int needsRedraw = 1;
  316.     int done = 0;
  317.     float xrot = 0.0;
  318.     float yrot = 0.0;
  319.     int x0, y0;
  320.     int i;
  321.  
  322.     for (i=1; i<argc; ++i) {
  323.     if ((strcmp("-geometry", argv[i]) == 0) && (i+1 < argc)) {
  324.         geometry = argv[++i];
  325.     }
  326.     }
  327.  
  328.     if ((dpy = XOpenDisplay(NULL)) == NULL) {
  329.     fprintf(stderr, "can't open display\n");
  330.     exit(EXIT_FAILURE);
  331.     }
  332.     scrn = DefaultScreen(dpy);
  333.     root = RootWindow(dpy, scrn);
  334.  
  335.     if ((vis = glXChooseVisual(dpy, scrn, visualAttrs)) == NULL) {
  336.     fprintf(stderr, "can't find visual\n");
  337.     exit(EXIT_FAILURE);
  338.     }
  339.  
  340.     if ((ctx = glXCreateContext(dpy, vis, NULL, True)) == NULL) {
  341.     fprintf(stderr, "can't create context\n");
  342.     exit(EXIT_FAILURE);
  343.     }
  344.  
  345.     sizehints.flags = PPosition | PSize;
  346.     sizehints.width = (int) width;
  347.     sizehints.height = (int) height;
  348.     sizehints.x = x;
  349.     sizehints.y = y;
  350.     if (geometry) {
  351.     int flags = XParseGeometry(geometry, &x, &y, &width, &height);
  352.  
  353.     if (flags & WidthValue) {
  354.        sizehints.flags |= USSize;
  355.        sizehints.width = (int) width;
  356.     }
  357.     if (flags & WidthValue) {
  358.        sizehints.flags |= USSize;
  359.        sizehints.height = (int) height;
  360.     }
  361.     if (flags & XValue) {
  362.        if (flags & XNegative) {
  363.            x = DisplayWidth(dpy, scrn) + x - sizehints.width;
  364.        }
  365.        sizehints.flags |= USPosition;
  366.        sizehints.x = x;
  367.     }
  368.     if (flags & YValue) {
  369.        if (flags & YNegative) {
  370.            y = DisplayHeight(dpy, scrn) + y - sizehints.height;
  371.        }
  372.        sizehints.flags |= USPosition;
  373.        sizehints.y = y;
  374.     }
  375.     }
  376.  
  377.     cmap = buildGrayScaleColormap(dpy, vis);
  378.  
  379.     swa.colormap = cmap;
  380.     swa.background_pixel = None;
  381.     swa.border_pixel = None;
  382.     win = XCreateWindow(dpy, root,
  383.             sizehints.x, sizehints.y,
  384.             sizehints.width, sizehints.height, 0,
  385.             vis->depth, InputOutput, vis->visual,
  386.             CWColormap | CWBackPixel | CWBorderPixel, &swa);
  387.     
  388.     XSetStandardProperties(dpy, win, name, name, None, argv, argc, &sizehints);
  389.     
  390.     XSelectInput(dpy, win,
  391.          StructureNotifyMask | ExposureMask |
  392.          KeyPressMask | ButtonPressMask | ButtonMotionMask);
  393.     
  394.     XMapWindow(dpy, win);
  395.     XIfEvent(dpy, &ev, waitForMapNotify, (XPointer) win);
  396.  
  397.     glXMakeCurrent(dpy, win, ctx);
  398.  
  399.     indexScale = (1 << vis->depth) - 1;
  400.     init();
  401.  
  402.     while (!done) {
  403.     do {
  404.         XNextEvent(dpy, &ev);
  405.         switch (ev.type) {
  406.           case KeyPress:
  407.         {
  408.             KeySym ks;
  409.             float p;
  410.  
  411.             XLookupString(&ev.xkey, NULL, 0, &ks, NULL);
  412.             switch (ks) {
  413.               case XK_Escape:
  414.             done = 1;
  415.             break;
  416.               case XK_O: case XK_o:
  417.             whichObject = (whichObject + 1) % NUM_OBJECTS;
  418.             break;
  419.               case XK_L: case XK_l:
  420.             useLighting = !useLighting;
  421.             break;
  422.               case XK_T: case XK_t:
  423.             useTwoSide = !useTwoSide;
  424.             break;
  425.               case XK_K: case XK_k:
  426.             useLocalLight = !useLocalLight;
  427.             break;
  428.               case XK_V: case XK_v:
  429.             useLocalViewer = !useLocalViewer;
  430.             break;
  431.               case XK_P: case XK_p:
  432.             useSpot = !useSpot;
  433.             break;
  434.               case XK_N: case XK_n:
  435.             useAtten = !useAtten;
  436.             break;
  437.               case XK_A:
  438.             p = matIndexRange[0] + 0.005;
  439.             if (p < 0.0) p = 0.0;
  440.             if (p > 1.0) p = 1.0;
  441.             matIndexRange[0] = p;
  442.             break;
  443.               case XK_a:
  444.             p = matIndexRange[0] - 0.005;
  445.             if (p < 0.0) p = 0.0;
  446.             if (p > 1.0) p = 1.0;
  447.             matIndexRange[0] = p;
  448.             break;
  449.               case XK_D:
  450.             p = matIndexRange[1] + 0.005;
  451.             if (p < 0.0) p = 0.0;
  452.             if (p > 1.0) p = 1.0;
  453.             matIndexRange[1] = p;
  454.             break;
  455.               case XK_d:
  456.             p = matIndexRange[1] - 0.005;
  457.             if (p < 0.0) p = 0.0;
  458.             if (p > 1.0) p = 1.0;
  459.             matIndexRange[1] = p;
  460.             break;
  461.               case XK_S:
  462.             p = matIndexRange[2] + 0.005;
  463.             if (p < 0.0) p = 0.0;
  464.             if (p > 1.0) p = 1.0;
  465.             matIndexRange[2] = p;
  466.             break;
  467.               case XK_s:
  468.             p = matIndexRange[2] - 0.005;
  469.             if (p < 0.0) p = 0.0;
  470.             if (p > 1.0) p = 1.0;
  471.             matIndexRange[2] = p;
  472.             break;
  473.               default:
  474.             break;
  475.             }
  476.         }
  477.         needsReconfig = 1;
  478.         needsRedraw = 1;
  479.         break;
  480.           case ButtonPress:
  481.         x0 = ev.xbutton.x;
  482.         y0 = ev.xbutton.y;
  483.         break;
  484.           case MotionNotify:
  485.         yrot += (float)(ev.xmotion.x-x0) * (360.0 / (float) width);
  486.         if (yrot > 360) yrot = yrot - 360;
  487.         if (yrot < 0) yrot = 360 - yrot;
  488.  
  489.         xrot += (float)(ev.xmotion.y-y0) * (360.0 / (float) height);
  490.         if (xrot > 360) xrot = xrot - 360;
  491.         if (xrot < 0) xrot = 360 - xrot;
  492.  
  493.         x0 = ev.xmotion.x; y0 = ev.xmotion.y;
  494.         needsRedraw = 1;
  495.         break;
  496.           case ConfigureNotify:
  497.         width = (unsigned int) ev.xconfigure.width;
  498.         height = (unsigned int) ev.xconfigure.height;
  499.         needsReconfig = 1;
  500.         needsRedraw = 1;
  501.         break;
  502.           case Expose:
  503.           default:
  504.         needsRedraw = 1;
  505.         break;
  506.         }
  507.     } while (XPending(dpy));
  508.  
  509.     if (needsReconfig) {
  510.         glViewport(0, 0, (float) width, (float) height);
  511.         reconfig();
  512.         needsReconfig = 0;
  513.     }
  514.  
  515.     if (needsRedraw) {
  516.         redraw(xrot, yrot);
  517.         glXSwapBuffers(dpy, win);
  518.         needsRedraw = 0;
  519.     }
  520.     }
  521. }
  522.